﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Mani.Common.Security;
using RastinArgham.CRM.Business;
using Mani.Common;
using Mani.Common.WorkflowEngine;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Data.Objects.DataClasses;

namespace RastinArgham.CRM.Web
{
    public partial class order_services : System.Web.UI.Page
    {
        public ISecurityManager securityManager { get; set; }
        public CRMRepository crmRepository { get; set; }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (securityManager == null)
            {
                securityManager = new SecurityManager();
                securityManager.authProvider = new WebAuthorizationProvider();
            }

            if (crmRepository == null)
                crmRepository = new CRMRepository();


            if (!securityManager.IsActionPermitted("order_services"))
                Response.Redirect("~/access_denied.aspx");

            pnlOrderProduct.Visible = securityManager.IsActionPermitted("submit_service_order");

            if (!Page.IsPostBack)
            {
                editOnlyTable.Visible = false;
                LoadCities();
                LoadServices();
                LoadOrders();
                LoadCancelationReasons();

                txtOrderDate.Text = DateTime.Now.ToJalali();
                txtServiceStartDate.Text = DateTime.Now.ToJalali();

                if (!String.IsNullOrEmpty(Request.QueryString["OrderId"]))
                {
                    LoadOrder();
                }
            }
        }

        #region Load Data

        private void LoadCities()
        {
            ddlInstallationCity.DataSource = crmRepository.FindCitiesByUser(securityManager.authProvider.GetCurrentUser().UserId);
            ddlInstallationCity.DataBind();
        }

        private void LoadCancelationReasons()
        {
            ddlCancelationReason.DataSource = crmRepository.GetCancelationReasons();
            ddlCancelationReason.DataBind();
        }

        private void LoadOrder()
        {
            int orderId = -1;
            if (!Int32.TryParse(Request.QueryString["OrderId"], out orderId) )
                return;

            if (!securityManager.IsActionPermitted("edit_order_services"))
                Response.Redirect("~/access_denied.aspx");

            Order o = crmRepository.GetOrderById(orderId);

            txtOrderId.Text = o.OrderId.ToString();
            txtFinancialRefNum.Text = o.FinancialRefNum;
            txtInstaller.Text = o.Installer;
            txtInvoiceNumber.Text = o.InvoiceNumber;
            
            txtOrderDate.Text = o.OrderDate.ToJalali();
            txtOrderDate.Enabled = false;

            txtServiceStartDate.Text = o.ServiceStartDate.ToJalali();
            txtServiceStartDate.Enabled = false;

            ddlServices.Items.FindByValue(o.ServiceId.Value.ToString()).Selected = true;
            ddlServices.Enabled = false;
            ddlServicePeriod.Items.FindByValue(o.Quantity.ToString()).Selected = true;
            ddlServicePeriod.Enabled = false;

            if (o.InstallationForm != null)
            {
                imgInstallationPhoto.Visible = true;
                imgInstallationPhoto.Src = "~/GetImage.ashx?ContactId=" + Request.QueryString["id"] + "&Type=OrderInstallationForm&OrderId=" + Request.QueryString["OrderId"] + "&w=50&h=50";
                aInstallationPhoto.Visible = true;
                aInstallationPhoto.Attributes.Add("href", "~/show_image.aspx?ContactId=" + Request.QueryString["id"] + "&Type=OrderInstallationForm&OrderId=" + Request.QueryString["OrderId"]);
            }


            if (o.InstallationPrice.HasValue)
            {
                ddlInstallationPrice.Items.FindByValue(o.InstallationPrice.Value.ToString()).Selected = true;
            }
            else
            {
                ddlInstallationPrice.ClearSelection();
            }

            editOnlyTable.Visible = true;

            // Load Installation Info
            InstallationInformation insinfo = o.InstallationInformations.FirstOrDefault();
            if (insinfo == null)
                return;

            ListItem item = ddlInstallationCity.Items.FindByValue(insinfo.CityId.ToString());
            if (item != null)
                item.Selected = true;

            txtInstallationRegion.Text = insinfo.Region;
            txtInstallationAddress.Text = insinfo.Address;
            txtInstallationBuildingName.Text = insinfo.BuildingName;
            txtInstallationPlaque.Text = insinfo.Plaque;
            txtInstallationFloor.Text = insinfo.Floor;
            txtUnitNumber.Text = insinfo.UnitNumber;
        }

        private void LoadOrders()
        {
            if (String.IsNullOrEmpty(Request.QueryString["id"]))
                return;

            Contact c = crmRepository.GetContactById(Convert.ToInt32(Request.QueryString["id"]));
            ContactInfo1.contact = c;
            ContactInfo1.DataBind();

            List<Order> orders = crmRepository.GetOrdersByContact(c.ContactId);
            
            if (orders.Count == 0)
                return;

            Guid currentUserId = securityManager.authProvider.GetCurrentUser().UserId;
            List<Guid> myAccountManagers = crmRepository.FindMyAccountManagers(currentUserId);

            if (!securityManager.IsActionPermitted("all_contacts") && c.AccountOwner != currentUserId && c.AccountManagerId != currentUserId & !myAccountManagers.Contains(c.AccountManagerId))
                Response.Redirect("~/access_denied.aspx");

            gvOrders.DataSource = orders.Where(o => o.ServiceId.HasValue).ToList();
            gvOrders.DataBind();

            
            ListItem item = ddlInstallationCity.Items.FindByValue(c.CityId.ToString());
            if (item != null)
            {
                ddlInstallationCity.ClearSelection();
                item.Selected = true;
            }
        }

        private void LoadServices()
        {
            if (String.IsNullOrEmpty(Request.QueryString["id"]))
                return;

            Contact c = crmRepository.GetContactById( Convert.ToInt32(Request.QueryString["id"]) );
            
            List<Service> services = new List<Service>();

            if (String.IsNullOrEmpty(Request.QueryString["OrderId"]))
            {
                services = crmRepository.GetEnabledServicesByProvince(c.City.ProvinceId);
            }
            else
            {
                services = crmRepository.GetServicesByProvince(c.City.ProvinceId);
            }

            ddlServices.DataSource = services;
            ddlServices.DataBind();
        }

        #endregion

        protected void btnSubmitOrder_Click(object sender, EventArgs e)
        {
            if (String.IsNullOrEmpty(Request.QueryString["id"]))
                return;

            if (String.IsNullOrEmpty(txtOrderId.Text) && String.IsNullOrEmpty(Request.QueryString["OrderId"]))
                New();
            else
                Update();
        }

        protected void gvOrders_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType != DataControlRowType.DataRow)
                return;

            int orderId = Convert.ToInt32(gvOrders.DataKeys[e.Row.RowIndex].Value);
            Order o = crmRepository.GetOrderById(orderId);

            WorkflowBasic wf = WorkflowFactory.Load(o.WorkflowInstanceId.Value);

            string[] roles = securityManager.authProvider.GetCurrentUser().aspnet_Roles.Select(r => r.RoleName).ToArray();
            ReadOnlyCollection<String> events = wf.GetPossibleEvents(roles);

            int i = 1;

            foreach (var item in events)
            {
                LinkButton link = (LinkButton)e.Row.FindControl("lbLink" + i.ToString());
                if (link != null)
                {
                    link.Visible = true;
                    link.Text = wf.GetEventDescription(item);
                    link.CommandName = item;
                    link.CommandArgument = o.WorkflowInstanceId.Value.ToString();
                }

                i++;
            }
        }

        protected void gvOrders_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            WorkflowBasic wf = WorkflowFactory.Load(new Guid(e.CommandArgument.ToString()));

            try
            {
                wf.SendEvent(e.CommandName, securityManager.authProvider.GetCurrentUser().UserId);
                LoadOrders();
            }
            catch (WorkflowException ex)
            {
                UIHelper.ClientAlert(this, ex.ErrorMessage);
            }
        }

        #region Add/Edit Order

        private void New()
        {
            Contact c = crmRepository.GetContactById(Convert.ToInt32(Request.QueryString["id"]));
            Service s = crmRepository.GetServiceById(Convert.ToInt32(ddlServices.SelectedValue));

            if (!s.Enable)
            {
                UIHelper.ClientAlert(this, "سرویس انتخاب شده برای فروش فعال نمی باشد");
                return;
            }

            if (s.ServicePeriod.Value > 1 && Convert.ToInt32(ddlServicePeriod.SelectedValue) != 1)
            {
                UIHelper.ClientAlert(this, "برای طرح های ویژه فقط انتخاب یک دوره مجاز می باشد");
                return;
            }

            Order o = new Order();
            o.Service = s;
            o.ServiceId = s.ServiceId;
            o.ServiceStartDate = txtServiceStartDate.Text.ToDateTime();
            o.ServiceExpirationDate = o.ServiceStartDate.Value.AddMonths(s.ServicePeriod.Value);
            o.ServiceExpired = false;
            o.AccountManagerId = c.AccountManagerId;
            o.Contact = c;
            o.ContactId = c.ContactId;
            o.Quantity = Convert.ToInt32(ddlServicePeriod.SelectedValue);
            o.Price = s.Price;
            o.TaxPercent = s.TaxPercent;
            o.OrderDate = txtOrderDate.Text.ToDateTime().Value;
            o.Activated = false;
            o.Registered = false;

            Guid OperatorId = securityManager.authProvider.GetCurrentUser().UserId;
            o.OperatorId = OperatorId;

            if (ddlCancelationReason.SelectedValue == "-1")
                o.CancelReasonId = null;
            else
                o.CancelReasonId = Convert.ToInt32(ddlCancelationReason.SelectedValue);

            crmRepository.NewOrder(o);

            InstallationInformation insinfo = new InstallationInformation();
            insinfo.CityId = Convert.ToInt32(ddlInstallationCity.SelectedValue);
            insinfo.Address = txtInstallationAddress.Text;
            insinfo.BuildingName = txtInstallationBuildingName.Text;
            insinfo.Floor = txtInstallationFloor.Text;
            insinfo.Plaque = txtInstallationPlaque.Text;
            insinfo.Region = txtInstallationRegion.Text;
            insinfo.UnitNumber = txtUnitNumber.Text;
            insinfo.Order = o;
            crmRepository.NewInstallationInfo(insinfo);

            crmRepository.Save();

            WorkflowBasic wf = WorkflowFactory.Create(typeof(ServiceOrderWorkflow), o.OrderId, OperatorId);
            o.WorkflowInstanceId = wf.InstanceId;
            wf.SendEvent(WorkflowState.GetEventName(1, 10), OperatorId);
            crmRepository.Save();

            UIHelper.ClientAlert(this, "تغییرات با موفقیت ذخیره شد");
            UIHelper.ClientRedirect(this, "order_services.aspx?id=" + Request.QueryString["id"]);
        }

        private void Update()
        {
            int orderId = -1;
            if (!Int32.TryParse(Request.QueryString["OrderId"], out orderId))
                return;

            if (!securityManager.IsActionPermitted("edit_order_services"))
                Response.Redirect("~/access_denied.aspx");

            Order o = crmRepository.GetOrderById(orderId);
            if (!o.ServiceId.HasValue)
                return;

            o.Installer = txtInstaller.Text;
            o.InvoiceNumber = txtInvoiceNumber.Text;
            o.FinancialRefNum = txtFinancialRefNum.Text;

            if (ddlInstallationPrice.SelectedValue == "-1")
                o.InstallationPrice = null;
            else
                o.InstallationPrice = Convert.ToInt64(ddlInstallationPrice.SelectedValue);

            Guid OperatorId = securityManager.authProvider.GetCurrentUser().UserId;
            o.OperatorId = OperatorId;
            o.LastUpdate = DateTime.Now;

            if (ddlCancelationReason.SelectedValue == "-1")
                o.CancelReasonId = null;
            else
                o.CancelReasonId = Convert.ToInt32(ddlCancelationReason.SelectedValue);

            string message = String.Empty;
            long MinSize = Convert.ToInt64(ConfigurationManager.AppSettings["minImageSize"]);
            long MaxSize = Convert.ToInt64(ConfigurationManager.AppSettings["maxImageSize"]);

            Byte[] PhotoBytes = UIHelper.CheckAndGetPostedImage(fuInstallationPhoto, out message, MinSize, MaxSize);
            if (!String.IsNullOrEmpty(message))
            {
                UIHelper.ClientAlert(this, message);
                return;
            }
            else if (PhotoBytes != null)
            {
                o.InstallationForm = PhotoBytes;
            }


            InstallationInformation insinfo;

            if (o.InstallationInformations.Count == 0)
                insinfo = new InstallationInformation();
            else
                insinfo = o.InstallationInformations.FirstOrDefault();

            insinfo.CityId = Convert.ToInt32(ddlInstallationCity.SelectedValue);
            insinfo.Address = txtInstallationAddress.Text;
            insinfo.BuildingName = txtInstallationBuildingName.Text;
            insinfo.Floor = txtInstallationFloor.Text;
            insinfo.Plaque = txtInstallationPlaque.Text;
            insinfo.Region = txtInstallationRegion.Text;
            insinfo.UnitNumber = txtUnitNumber.Text;
            insinfo.Order = o;

            if (o.InstallationInformations.Count == 0)
                crmRepository.NewInstallationInfo(insinfo);

            crmRepository.Save();
            UIHelper.ClientAlert(this, "تغییرات با موفقیت ذخیره شد");
            UIHelper.ClientRedirect(this, "order_services.aspx?id=" + Request.QueryString["id"]);
        }

        #endregion
    }
}